#include "clib_sock.h"
#include "clib_stack_trace.h"
#include "clib_stack.h"
#include <stdlib.h>

static __thread unsigned int seed;

void
clib_sock_init(clib_sock_t* sock,i32_t sfd)
{
    memset(sock, 0, sizeof(clib_sock_t));
    
    clib_queue_init(&sock->list);
    clib_queue_init(&sock->ack_list);
    clib_queue_init(&sock->wack_list);
    clib_queue_init(&sock->recv_list);
    clib_queue_init(&sock->send_list);
    clib_queue_init(&sock->ep_list);
    clib_queue_init(&sock->timerto_list);
    clib_queue_init(&sock->timewait_list);
    clib_queue_init(&sock->timeout_list);
    clib_queue_init(&sock->tuple_list);

    sock->sock_id = sfd;
}

void
clib_sock_clean(clib_sock_t* sock)
{
    clib_queue_del(&sock->list);
    clib_queue_del(&sock->ack_list);
    clib_queue_del(&sock->wack_list);
    clib_queue_del(&sock->recv_list);
    clib_queue_del(&sock->send_list);
    clib_queue_del(&sock->ep_list);
    clib_queue_del(&sock->timerto_list);
    clib_queue_del(&sock->timewait_list);
    clib_queue_del(&sock->timeout_list);
    clib_queue_del(&sock->tuple_list);
    /** TODO 清理tcp_stream **/
    /** TODO 清理udp_stream **/
    /** TODO 清理ep_stream  **/
    /** TODO 清理listen     **/

}

i32_t
clib_sock_ipv4_init(clib_sock_t* sock, sock_type_t type, tuple_t *tuple)
{
    tcp_stream_t *stream;
    tcp_listen_t *listen;
    clib_epoll_t *epoll;

    sock->sock_type = type;
    sock->ipv4      = 1;

    if(type == socket_type_sock_tcp) {
       
        sock->ipv4_tuple = tuple->ipv4_tuple;

        /** TODO 添加缩放因子 **/
        stream = &sock->tcp_stream;
        stream->ttl = 128;
        stream->multicast_ttl = 64;
        stream->iss = rand_r(&seed);
        stream->irs = 0;
        stream->snd_nxt = stream->iss;
        stream->snd_una = stream->iss;
        stream->snd_wnd = stack_cfg.send_buf;
        stream->rcv_nxt = 0;
        stream->rcv_wnd = 14600;
        stream->snd_wl1 = stream->iss;
        sock->ip_id = 0;
    } else if(type == socket_type_epoll) {

    } else if(type == socket_type_listen) {

    } else {
        clib_stack_trace("socket type unknow (%s:%d)\n",__FILE__,__LINE__);
        return rn_error;
    }
    return rn_ok;
}

i32_t
clib_sock_ipv6_init(clib_sock_t* sock, sock_type_t type, tuple_t *tuple)
{
    tcp_stream_t *stream;
    tcp_listen_t *listen;
    clib_epoll_t *epoll;

    sock->sock_type = type;
    sock->ipv4      = 0;

    if(type == socket_type_sock_tcp) {
       
        sock->ipv6_tuple = tuple->ipv6_tuple;

        /** TODO 添加缩放因子 **/
        stream = &sock->tcp_stream;
        stream->ttl = 128;
        stream->multicast_ttl = 64;
        stream->iss = rand_r(&seed);
        stream->irs = 0;
        stream->snd_nxt = stream->iss;
        stream->snd_una = stream->iss;
        stream->snd_wnd = stack_cfg.send_buf;
        stream->rcv_nxt = 0;
        stream->rcv_wnd = 14600;
        stream->snd_wl1 = stream->iss;
        sock->ip_id = 0;
    } else if(type == socket_type_epoll) {

    } else if(type == socket_type_listen) {

    } else {
        clib_stack_trace("socket type unknow (%s:%d)\n",__FILE__,__LINE__);
        return rn_error;
    }
    return rn_ok;
}